﻿using System;
using System.IO;
using Bussiness.Model;
using Bussiness.Exception;
using NHibernate;
using NHibernate.Cfg;
using NHibernate.Tool.hbm2ddl;
using NHibernate.Mapping.Attributes;

namespace Bussiness.Utilities
{
    public class HibernateHelper
    {
        public static readonly ISessionFactory SessionFactory;
        private static readonly string AppPath = AppDomain.CurrentDomain.SetupInformation.ApplicationBase;
        private const string MappingFileName = "Domain.hbm.xml";

        static HibernateHelper()
        {
            try
            {
                var cfg = new Configuration().Configure();
                cfg.SetNamingStrategy(new DmNamingStrategy());
                ConfigMapping(cfg, false);
                SessionFactory = cfg.BuildSessionFactory();
            }
            catch (System.Exception ex)
            {
                throw new InfrastructureException("NHibernate initilization failed.", ex);
            }
        }

        private static void ConfigMapping(Configuration cfg, bool check)
        {
            HbmSerializer.Default.Validate = true;
            using (var stream = HbmSerializer.Default.Serialize(typeof(Category).Assembly))
            {
                if (check)
                {
                    cfg.AddInputStream(stream, MappingFileName);
                }
                else
                {
                    cfg.AddInputStream(stream);
                }
            }
        }

        public static void DumpMappingToFile()
        {
            HbmSerializer.Default.Validate = true;
            using (var stream = HbmSerializer.Default.Serialize(typeof(Category).Assembly))
            {
                stream.Position = 0;
                try
                {
                    var binaryReader = new BinaryReader(stream);
                    Stream toStream = File.Create(Path.Combine(AppPath, MappingFileName));
                    var binaryWriter = new BinaryWriter(toStream);
                    binaryWriter.Write(binaryReader.ReadBytes((int)stream.Length));
                    binaryWriter.Flush();
                }
                catch (System.Exception ex)
                {
                    throw new InfrastructureException("Cannot dump mapping file!", ex);
                }
            }
        }

        public static void DropDatabseObjects()
        {
            var cfg = new Configuration().Configure();
            cfg.SetNamingStrategy(new DmNamingStrategy());
            ConfigMapping(cfg, false);
            var se = new SchemaExport(cfg);
            se.Drop(false,true);
        }

        public static void CreateDatabseObjects()
        {
            var cfg = new Configuration().Configure();
            cfg.SetNamingStrategy(new DmNamingStrategy());
            ConfigMapping(cfg, false);
            var se = new SchemaExport(cfg);
            se.Create(false, true);
        }

        public static ISession OpenSession()
        {
            return SessionFactory.OpenSession();
        }

        public static ISession GetCurrentSession()
        {
            return SessionFactory.GetCurrentSession();
        }
    }
}
